import axios from 'axios'
import config from '../config'
import { ElMessage } from 'element-plus'
import router from '../router'
import storage from './storage'

const TOKEN_ERROR = 'Token认证失败，请重新登录'
const NETWORK_ERROR = '网络请求异常，请稍后重试'

// 常见 axios 的实例对象，添加配置
const service = axios.create({
  baseURL: config.baseApi,
  timeout: 8000
})

// 请求
service.interceptors.request.use((req) => {
  // 一些公共的请求机制
  const header = req.headers
  // TODO: 添加 token，处理第一次登陆时，storage 中没有 token 的情况
  const { token } = storage.getItem('userInfo') || {}
  
  // 添加请求头权限
  if (!header.Authorization) header.Authorization = 'Bearer ' + token;
  return req
})

// 响应
service.interceptors.response.use((res) => {
  // 一些公共的响应机制
  const { code, data, msg } = res.data
  if(code === 200) {
    return data
  } else if(code === 50001) {
    ElMessage.error(TOKEN_ERROR)
    setTimeout(() => {
      router.push('/login')
    }, 1500)
    return Promise.reject(TOKEN_ERROR)
  } else {
    ElMessage.error(msg || NETWORK_ERROR)
    return Promise.reject(msg || NETWORK_ERROR)
  }
})

// 核心的 request 函数
function request(options) {
  // 请求类型
  options.method = options.method || 'get'
  // 请求类型转大小写
  if(options.method.toLowerCase() === 'get') {
    // 统一参数属性为 data
    options.params = options.data || {}
  }
  let isMock = config.mock
  if(typeof options.mock !== 'undefined') {
    isMock = options.mock
  }
  // 重点：请求基础地址置顶，避免不同环境获取错误数据
  if(config.env === 'prod') {
    service.defaults.baseURL = config.baseApi
  } else {
    service.defaults.baseURL = isMock ? config.mockApi : config.baseApi
  }
  return service(options)
}

// 支持 this.$request.get('/login', {name: 'viking'}, {mock: true}) 等方法
['get', 'post', 'put', 'delete', 'patch'].forEach((item) => {
  request[item] = (url, data, options) => {
    return request({
      url,
      data,
      method: item,
      ...options
    })
  }
})

export default request